package com.ls.httpstudy.http.configuration;


import io.netty.channel.ChannelOption;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;


import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.reactive.*;
import org.springframework.web.reactive.function.client.ExchangeStrategies;
import org.springframework.web.reactive.function.client.WebClient;

import reactor.netty.http.client.HttpClient;
import reactor.netty.resources.ConnectionProvider;
import reactor.netty.resources.LoopResources;

import java.time.Duration;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;


@Configuration
public class WebClientConfig {

    @Deprecated
    @Bean
    public JettyResourceFactory jettyResourceFactory() {
        return new JettyResourceFactory();
    }
    @Deprecated
    @Bean(name = "jettyWebClient")
    public WebClient myWebClient() { ;
        org.eclipse.jetty.client.HttpClient httpClient = new org.eclipse.jetty.client.HttpClient();
        ClientHttpConnector connector =
                new JettyClientHttpConnector(httpClient, jettyResourceFactory());
        return WebClient.builder().clientConnector(connector).build();
    }


    @Bean(name = "defaultWebClient")
    public WebClient webClient() {
        WebClient webClient = null;

        //配置动态连接池
//        ConnectionProvider provider = ConnectionProvider.elastic("elastic pool");
        //配置固定大小连接池，如最大连接数、连接获取超时、空闲连接死亡时间等
//        ConnectionProvider provider = ConnectionProvider.fixed("fixed", 45, 4000, Duration.ofSeconds(6));
        ConnectionProvider provider = ConnectionProvider.builder("fixed").maxConnections(45).pendingAcquireTimeout(Duration.ofSeconds(6)).maxLifeTime(Duration.ofSeconds(6)).build();
        HttpClient httpClient = HttpClient.create(provider)
//                .secure(sslContextSpec -> {
//                    SslContextBuilder sslContextBuilder = SslContextBuilder.forClient()
//                            .trustManager(new File("E://server.truststore"));
//                    sslContextSpec.sslContext(sslContextBuilder);
//                })
                .tcpConfiguration(tcpClient -> {
                    //指定Netty的select 和 work线程数量
                    LoopResources loop = LoopResources.create("kl-event-loop", 1, 4, true);
                    return tcpClient.doOnConnected(connection -> {
                        //读写超时设置
                        connection.addHandlerLast(new ReadTimeoutHandler(10, TimeUnit.SECONDS))
                                .addHandlerLast(new WriteTimeoutHandler(10));
                    })
                            //连接超时设置
                            .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)
                            .option(ChannelOption.TCP_NODELAY, true)
                            .runOn(loop);
                });


        WebClient.Builder builder = WebClient.builder()
                .clientConnector(new ReactorClientHttpConnector(httpClient))
                .exchangeStrategies(ExchangeStrategies.builder().codecs(configurer ->
                        configurer.defaultCodecs()
                                .maxInMemorySize(10 * 1024 * 1024)).build()
                );

        webClient = builder.build();
        return webClient;
    }

    @Deprecated
    @Bean
    public ReactorResourceFactory resourceFactory() {
        ReactorResourceFactory factory = new ReactorResourceFactory();
        factory.setUseGlobalResources(false);
        factory.setConnectionProvider(ConnectionProvider.builder("httpClient").maxConnections(45).pendingAcquireTimeout(Duration.ofSeconds(6)).maxLifeTime(Duration.ofSeconds(6)).build());
        factory.setLoopResources(LoopResources.create("httpClient", 50, true));
        return factory;
    }

    @Deprecated
    @Bean(name = "webClientTest")
    public WebClient webClientTest() {
        Function<HttpClient, HttpClient> mapper = client ->
                client.tcpConfiguration(c ->
                        c.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10)
                                .option(ChannelOption.TCP_NODELAY, true)
                                .doOnConnected(conn -> {
                                    conn.addHandlerLast(new ReadTimeoutHandler(10));
                                    conn.addHandlerLast(new WriteTimeoutHandler(10));
                                }));

        ClientHttpConnector connector = new ReactorClientHttpConnector(resourceFactory(), mapper);

        return WebClient.builder().clientConnector(connector).build();

    }
}
